package pl.edu.agh.neuraleconomy.core.nn;

import java.util.LinkedList;
import java.util.List;

import lombok.Getter;
import lombok.Setter;

import org.encog.ml.data.MLDataSet;
import org.encog.ml.train.MLTrain;
import org.encog.neural.networks.training.propagation.back.Backpropagation;
import org.encog.neural.networks.training.propagation.resilient.ResilientPropagation;

public class NetworkTrainer {

	@Setter
	private SimpleNetwork network;
	@Setter
	private int maxIterations = 10000;
	@Setter
	private double learningRate = 0.75;
	@Setter
	private double momentum = 0.1;
	@Setter
	private MLDataSet dataSet = null;
	@Setter
	private double maxAllowedError = 0.0001;

	@Getter
	private List<Double> errors = new LinkedList<Double>();

	public void train() {
		validate();

		MLTrain train = getTrain();

		int i = 0;
		double error = Double.MAX_VALUE;
		do {
			train.iteration();
			error = train.getError();
			errors.add(error);
			i++;
		} while (i < maxIterations && error > maxAllowedError);
	}

	private MLTrain getTrain() {
		Backpropagation train = new Backpropagation(network.getNetwork(), getDataSet());
		train.setLearningRate(learningRate);
		train.setMomentum(momentum);

		return new ResilientPropagation(network.getNetwork(), getDataSet());
	}

	private MLDataSet getDataSet() {
		return dataSet;
	}

	private void validate() {
		if (network == null || network.getNetwork() == null) {
			throw new IllegalStateException("Network cannot be null");
		}

		if (dataSet == null) {
			throw new IllegalStateException("Dataset cannot be null");
		}
	}

}
